//! 错误处理模块
//! 
//! 这个模块定义了应用程序中使用的错误类型和错误处理机制。
//! 使用thiserror和anyhow库来提供类型安全的错误处理。

use axum::{
    http::StatusCode,
    response::{IntoResponse, Response},
    Json,
};
use serde_json::json;
use thiserror::Error;

/// 应用程序错误类型
/// 
/// 使用thiserror宏自动生成Error trait的实现，
/// 并提供统一的错误处理机制
#[derive(Error, Debug)]
pub enum AppError {
    /// 数据库相关错误
    #[error("数据库错误: {0}")]
    Database(#[from] sqlx::Error),

    /// Redis相关错误
    #[error("Redis错误: {0}")]
    Redis(#[from] redis::RedisError),

    /// JWT相关错误
    #[error("JWT错误: {0}")]
    Jwt(#[from] jsonwebtoken::errors::Error),

    /// 配置错误
    #[error("配置错误: {0}")]
    Config(#[from] config::ConfigError),

    /// 密码哈希错误
    #[error("密码哈希错误: {0}")]
    PasswordHash(String),

    /// 序列化/反序列化错误
    #[error("序列化错误: {0}")]
    Serialization(#[from] serde_json::Error),

    /// IO错误
    #[error("IO错误: {0}")]
    Io(#[from] std::io::Error),

    /// Prometheus错误
    #[error("Prometheus错误: {0}")]
    Prometheus(#[from] prometheus::Error),

    /// 验证错误
    #[error("验证错误: {message}")]
    Validation { message: String },

    /// 未授权错误
    #[error("未授权访问")]
    Unauthorized,

    /// 权限不足错误
    #[error("权限不足")]
    Forbidden,

    /// 资源未找到错误
    #[error("资源未找到")]
    NotFound,

    /// 冲突错误（如重复资源）
    #[error("资源冲突: {message}")]
    Conflict { message: String },

    /// 请求过大错误
    #[error("请求过大")]
    PayloadTooLarge,

    /// 内部服务器错误
    #[error("内部服务器错误")]
    InternalServerError,

    /// 服务不可用错误
    #[error("服务不可用")]
    ServiceUnavailable,
}

/// 应用程序结果类型别名
/// 
/// 这是Result<T, AppError>的简写，用于整个应用程序中
pub type AppResult<T> = Result<T, AppError>;

/// 实现IntoResponse trait，将AppError转换为HTTP响应
/// 
/// 这个实现确保所有的AppError都能自动转换为合适的HTTP响应，
/// 包括正确的状态码和JSON错误信息
impl IntoResponse for AppError {
    fn into_response(self) -> Response {
        let (status, error_code, message, details) = match self {
            // 数据库错误
            AppError::Database(ref e) => {
                tracing::error!("数据库错误: {}", e);
                (
                    StatusCode::INTERNAL_SERVER_ERROR,
                    "DATABASE_ERROR".to_string(),
                    "数据库操作失败".to_string(),
                    Some(serde_json::to_value(e.to_string()).unwrap_or_default()),
                )
            }

            // Redis错误
            AppError::Redis(ref e) => {
                tracing::error!("Redis错误: {}", e);
                (
                    StatusCode::INTERNAL_SERVER_ERROR,
                    "REDIS_ERROR".to_string(),
                    "缓存操作失败".to_string(),
                    Some(serde_json::to_value(e.to_string()).unwrap_or_default()),
                )
            }

            // JWT错误
            AppError::Jwt(ref e) => {
                tracing::warn!("JWT错误: {}", e);
                (
                    StatusCode::UNAUTHORIZED,
                    "JWT_ERROR".to_string(),
                    "身份验证失败".to_string(),
                    None,
                )
            }

            // 配置错误
            AppError::Config(ref e) => {
                tracing::error!("配置错误: {}", e);
                (
                    StatusCode::INTERNAL_SERVER_ERROR,
                    "CONFIG_ERROR".to_string(),
                    "配置加载失败".to_string(),
                    Some(serde_json::to_value(e.to_string()).unwrap_or_default()),
                )
            }

            // 密码哈希错误
            AppError::PasswordHash(ref e) => {
                tracing::error!("密码哈希错误: {}", e);
                (
                    StatusCode::INTERNAL_SERVER_ERROR,
                    "PASSWORD_HASH_ERROR".to_string(),
                    "密码处理失败".to_string(),
                    None,
                )
            }

            // 序列化错误
            AppError::Serialization(ref e) => {
                tracing::warn!("序列化错误: {}", e);
                (
                    StatusCode::BAD_REQUEST,
                    "SERIALIZATION_ERROR".to_string(),
                    "数据格式错误".to_string(),
                    Some(serde_json::to_value(e.to_string()).unwrap_or_default()),
                )
            }

            // IO错误
            AppError::Io(ref e) => {
                tracing::error!("IO错误: {}", e);
                (
                    StatusCode::INTERNAL_SERVER_ERROR,
                    "IO_ERROR".to_string(),
                    "文件操作失败".to_string(),
                    Some(serde_json::to_value(e.to_string()).unwrap_or_default()),
                )
            }

            // 验证错误
            AppError::Validation { message } => {
                tracing::warn!("验证错误: {}", message);
                (
                    StatusCode::BAD_REQUEST,
                    "VALIDATION_ERROR".to_string(),
                    message,
                    None,
                )
            }

            // 未授权错误
            AppError::Unauthorized => {
                tracing::warn!("未授权访问");
                (
                    StatusCode::UNAUTHORIZED,
                    "UNAUTHORIZED".to_string(),
                    "未授权访问".to_string(),
                    None,
                )
            }

            // 权限不足错误
            AppError::Forbidden => {
                tracing::warn!("权限不足");
                (
                    StatusCode::FORBIDDEN,
                    "FORBIDDEN".to_string(),
                    "权限不足".to_string(),
                    None,
                )
            }

            // 资源未找到错误
            AppError::NotFound => {
                tracing::warn!("资源未找到");
                (
                    StatusCode::NOT_FOUND,
                    "NOT_FOUND".to_string(),
                    "请求的资源不存在".to_string(),
                    None,
                )
            }

            // 冲突错误
            AppError::Conflict { message } => {
                tracing::warn!("资源冲突: {}", message);
                (
                    StatusCode::CONFLICT,
                    "CONFLICT".to_string(),
                    message,
                    None,
                )
            }

            // 请求过大错误
            AppError::PayloadTooLarge => {
                tracing::warn!("请求过大");
                (
                    StatusCode::PAYLOAD_TOO_LARGE,
                    "PAYLOAD_TOO_LARGE".to_string(),
                    "请求体过大".to_string(),
                    None,
                )
            }

            // 内部服务器错误
            AppError::InternalServerError => {
                tracing::error!("内部服务器错误");
                (
                    StatusCode::INTERNAL_SERVER_ERROR,
                    "INTERNAL_SERVER_ERROR".to_string(),
                    "内部服务器错误".to_string(),
                    None,
                )
            }

            // 服务不可用错误
            AppError::ServiceUnavailable => {
                tracing::error!("服务不可用");
                (
                    StatusCode::SERVICE_UNAVAILABLE,
                    "SERVICE_UNAVAILABLE".to_string(),
                    "服务暂时不可用".to_string(),
                    None,
                )
            }

            // Prometheus错误
            AppError::Prometheus(e) => {
                tracing::error!("Prometheus错误: {}", e);
                (
                    StatusCode::INTERNAL_SERVER_ERROR,
                    "PROMETHEUS_ERROR".to_string(),
                    "监控系统错误".to_string(),
                    Some(serde_json::to_value(e.to_string()).unwrap_or_default()),
                )
            }
        };

        // 构建错误响应
        let error_response = json!({
            "success": false,
            "error": {
                "code": error_code,
                "message": message,
                "details": details,
                "timestamp": chrono::Utc::now().to_rfc3339(),
            }
        });

        (status, Json(error_response)).into_response()
    }
}

/// 便捷的错误创建函数
impl AppError {
    /// 创建验证错误
    pub fn validation(message: impl Into<String>) -> Self {
        Self::Validation {
            message: message.into(),
        }
    }

    /// 创建冲突错误
    pub fn conflict(message: impl Into<String>) -> Self {
        Self::Conflict {
            message: message.into(),
        }
    }

    /// 检查是否是数据库唯一约束违反错误
    pub fn is_database_unique_violation(&self) -> bool {
        match self {
            AppError::Database(sqlx::Error::Database(db_err)) => {
                db_err.is_unique_violation()
            }
            _ => false,
        }
    }

    /// 检查是否是数据库外键约束违反错误
    pub fn is_database_foreign_key_violation(&self) -> bool {
        match self {
            AppError::Database(sqlx::Error::Database(db_err)) => {
                db_err.is_foreign_key_violation()
            }
            _ => false,
        }
    }

    /// 检查是否是数据库行未找到错误
    pub fn is_database_row_not_found(&self) -> bool {
        matches!(self, AppError::Database(sqlx::Error::RowNotFound))
    }
}

/// 用于anyhow的转换实现
impl From<anyhow::Error> for AppError {
    fn from(err: anyhow::Error) -> Self {
        tracing::error!("Anyhow错误: {}", err);
        Self::InternalServerError
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_validation_error() {
        let error = AppError::validation("测试验证错误");
        assert!(matches!(error, AppError::Validation { .. }));
    }

    #[test]
    fn test_conflict_error() {
        let error = AppError::conflict("测试冲突错误");
        assert!(matches!(error, AppError::Conflict { .. }));
    }

    #[test]
    fn test_error_into_response() {
        let error = AppError::NotFound;
        let response = error.into_response();
        assert_eq!(response.status(), StatusCode::NOT_FOUND);
    }
}
